use crate::cljcell::clj_cell::CljCell;
use crate::built_in_functions::my_clojure_interp::{CljFunc, CljRecur, MyClojureInterp, CljFuncParam, CljFuncParamList, MyCljFunc, MyFuncHs, MyCljRecur};
use crate::built_in_functions::util::my_util;
use crate::built_in_functions::my_funs::MyFunctions;
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;
use std::cell::RefCell;

pub struct MyClj;

impl MyClj {
    /**
     * let 语句
     * */
    pub fn clj_list_let(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        if lst.len() >= 3 {
            let bindings: &Rc<CljCell> = &lst[1];
            match &**bindings {
                CljCell::BracketClj(vs) => {
                    let mut i = 0;
                    while i < vs.len() && i + 1 < vs.len() {
                        let c1: &Rc<CljCell> = &vs[i];
                        let c2: &Rc<CljCell> = &vs[i + 1];
                        match &**c1 {
                            CljCell::Symbol(sym_line) => {
                                unsafe {
                                    let rs1: Rc<CljCell> = interp.eval(&c2, func_hs, clj_recur, rs.clone());
                                    func_hs.insert(sym_line.as_ref().clone(), rs1);
                                }
                            },
                            CljCell::Percent(sym_line) => {},
                            _ => {},
                        }
                        i += 2;
                    }

                    i = 2;
                    while i < lst.len() {
                        if i == lst.len() - 1 {
                            unsafe {
                                return interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                            }
                        } else {
                            unsafe {
                                interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                            }
                        }
                        i += 1;
                    }
                },
                _ => {},
            }
        }
        return Rc::new(CljCell::Null);
    }

    /**
     * recur 语句
     * */
    pub fn clj_list_recur(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        if lst.len() > 1 {
            match &**(clj_recur.get_func_cell_body()) {
                CljCell::Null => {
                    let mut subht: HashMap<String, Rc<CljCell>> = HashMap::new();
                    for i in 1..lst.len() {
                        let rs1 = interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                        // let my_ht1 = CljRecur.get_ht_mut();
                        // let key: String = my_ht1.get(&(i as i32)).unwrap().to_string();
                        let key: String = clj_recur.get_ht_value(&(i as i32)).to_string();
                        subht.insert(key, rs1);
                    }

                    for key in subht.keys() {
                        let htvs: Rc<CljCell> = subht.get(&key.to_string()).unwrap().clone();
                        //let cr = Rc::make_mut(&mut func_hs);
                        //cr.insert(key.to_string(), htvs);
                        func_hs.insert(key.to_string(), htvs);
                    }

                    let cell1: &Rc<CljCell> = clj_recur.get_clj_cell();
                    return interp.eval(cell1, func_hs, clj_recur, rs.clone());
                },
                _ => {
                    let mut lstrs: Vec<Rc<CljCell>> = Vec::new();
                    for i in 1..lst.len() {
                        let tmp = interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                        if let CljCell::List(vss) = &*tmp {
                            let mut rs1: Vec<Rc<CljCell>> = Vec::new();
                            let ls1: &Vec<Rc<CljCell>> = vss;
                            for n in ls1 {
                                //println!("吴大富 {:?}", n.clone());
                                rs1.push(n.clone());
                            }
                            //println!("大 {:?}", rs1);
                            lstrs.push(Rc::new(CljCell::List(rs1)));
                        }
                        else {
                            lstrs.push(tmp);
                        }
                        // println!("tmp {:?}", tmp);
                        // lstrs.push(tmp);
                    }

                    // 修改传入参数的值
                    let ht: HashMap<String, Rc<CljCell>> = MyFunctions::get_params(clj_recur.get_clj_func_param_list(), &lstrs);
                    // recur 一定是带参数的，不许不带参数，不然容易死循环
                    if ht.len() > 0 {
                        for (k, v) in &ht {
                            func_hs.insert(k.to_string(), v.clone());
                        }

                        // unsafe {
                        //     println!("A 后 {:?}", *func_hs.ptr);
                        // }

                        return interp.eval(clj_recur.get_func_cell_body(), func_hs, clj_recur, rs.clone());
                    }

                    // for (k, v) in &ht {
                    //     func_hs.insert(k.to_string(), v.clone());
                    // }
                    //
                    // return interp.eval(CljRecur.get_func_cell_body(), func_hs, CljRecur, rs.clone());
                },
            }
        }
        return Rc::new(CljCell::Null);
    }

    /**
     * loop 语句
     * */
    pub fn clj_list_loop(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, mut func_hs: &MyFuncHs, mut clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        if lst.len() >= 3 {
            let bindings = &lst[1];
            if let CljCell::BracketClj(pss) = &**bindings {
                //let cljRecur1: Box<CljRecur> = Box::new(CljRecur::new());
                //let ptr = Box::into_raw(cljRecur1);
                let mut index = 1;
                let mut i = 0;
                while i < pss.len() {
                    let c1 = &pss[i];
                    let c2 = &pss[i + 1];
                    match &**c1 {
                        CljCell::Symbol(sys_name) => {
                            let rs1 = interp.eval(&c2, func_hs, clj_recur, rs.clone());
                            func_hs.insert((**sys_name).clone(), rs1);
                            clj_recur.insert_ht(index, (**sys_name).clone());
                            index += 1;
                        },
                        CljCell::Percent(sys_name) => {},
                        _ => {},
                    }

                    i += 2;
                }

                i = 2;
                while i < lst.len() {
                    clj_recur.set_clj_cell(lst[i].clone());
                    if i == lst.len() - 1 {
                        return interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                    } else {
                        interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                    }
                }
            }
        }
        return Rc::new(CljCell::Null);
    }

    /**
     * do 计算
     * */
    pub fn clj_list_do(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        if lst.len() > 1 {
            for i in 1..lst.len() {
                if i == lst.len() - 1 {
                    return interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                } else {

                    interp.eval(&lst[i], func_hs, clj_recur, rs.clone());
                }
            }
        }
        return Rc::new(CljCell::Null);
    }

    /**
     * list 计算
     * */
    pub fn clj_list_list(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        let mut lstrs: Vec<Rc<CljCell>> = Vec::new();
        for c in lst {
            lstrs.push(interp.eval(&c, func_hs, clj_recur, rs.clone()));
        }
        return Rc::new(CljCell::List(lstrs));
    }

    /**
     * def 语句
     * */
    pub fn clj_list_def(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, mut func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        if lst.len() >= 3 {
            let name: &Rc<CljCell> = &lst[1];
            match &**name {
                CljCell::Symbol(sys_name) => {
                    let vs =interp.eval(&lst[lst.len() - 1], func_hs, clj_recur, rs.clone());
                    func_hs.insert((**sys_name).clone(), vs);
                },
                CljCell::Percent(sys_name) => {},
                _ => {},
            }
        }
        return Rc::new(CljCell::Null);
    }

    /**
     * apply 计算
     * */
    pub fn clj_list_apply(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        // apply 计算
        let apply_lst = &lst[1..];
        let mut apply_lst_new: Vec<Rc<CljCell>> = Vec::new();
        apply_lst_new.push(apply_lst[0].clone());

        match &*apply_lst[1] {
            CljCell::List(vs) => {
                for n in vs {
                    apply_lst_new.push(n.clone());
                }
            },
            CljCell::BracketClj(vs) => {
                for n in vs {
                    apply_lst_new.push(n.clone());
                }
            },
            CljCell::Symbol(vs) => {
                let c: &Rc<CljCell> = func_hs.get(&*vs);
                match &**c {
                    CljCell::CljList(vs) => {
                        let c1 = interp.clj_list(vs, func_hs, clj_recur, rs.clone());
                        apply_lst_new.push(c1);
                    },
                    CljCell::List(vs) => {
                        for n in vs {
                            apply_lst_new.push(n.clone());
                        }
                    },
                    CljCell::Set(vs) => {
                        for n in vs {
                            apply_lst_new.push(n.clone());
                        }
                    },
                    CljCell::BracketClj(vs) => {
                        for n in vs {
                            apply_lst_new.push(n.clone());
                        }
                    },
                    CljCell::HashTable(vs) => {},
                    _ => {},
                }
            },
            CljCell::Percent(vs) => {},
            _ => {},
        }

        // unsafe {
        //     println!("*************");
        //     println!("{:?}", *interp.ptr);
        //     println!("{:?}", *func_hs.ptr);
        //     println!("{:?}", *CljRecur.ptr);
        //     println!("{:?}", apply_lst_new);
        //     println!("$$$$$$$$$$$$$");
        // }
        return interp.clj_list(&apply_lst_new, func_hs, clj_recur, rs.clone());
    }

    /**
     * else 计算
     * */
    pub fn clj_list_else(interp: &MyClojureInterp, lst: &Vec<Rc<CljCell>>, func_hs: &MyFuncHs, clj_recur: &MyCljRecur, rs: Rc<CljCell>) -> Rc<CljCell> {
        // apply 计算
        let apply_lst = &lst[1..];
        let mut apply_lst_new: Vec<Rc<CljCell>> = Vec::new();
        apply_lst_new.push(apply_lst[0].clone());

        match &*apply_lst[1] {
            CljCell::List(vs) => {
                for n in vs {
                    apply_lst_new.push(n.clone());
                }
            },
            CljCell::BracketClj(vs) => {
                for n in vs {
                    apply_lst_new.push(n.clone());
                }
            },
            CljCell::Symbol(vs) => {
                let c: &Rc<CljCell> = func_hs.get(&*vs);
                match &**c {
                    CljCell::CljList(vs) => {
                        let c1 = interp.clj_list(vs, func_hs, clj_recur, rs.clone());
                        apply_lst_new.push(c1);
                    },
                    CljCell::List(vs) => {
                        for n in vs {
                            apply_lst_new.push(n.clone());
                        }
                    },
                    CljCell::Set(vs) => {
                        for n in vs {
                            apply_lst_new.push(n.clone());
                        }
                    },
                    CljCell::BracketClj(vs) => {
                        for n in vs {
                            apply_lst_new.push(n.clone());
                        }
                    },
                    CljCell::HashTable(vs) => {},
                    _ => {},
                }
            },
            CljCell::Percent(vs) => {},
            _ => {},
        }

        return interp.clj_list(&apply_lst_new, func_hs, clj_recur, rs.clone());
    }
}





















































